#include <stdlib.h>
#include <locale.h>
#include "boost/locale/encoding.hpp"
#include "BSException/BSException.h"
#include "UTF8.h"
#include "Unicode.h"

#define UTF8_ENCODE_STRING "UTF8"

#define GBK_ENCODE_STRING "GBK"

#define GB2312_ENCODE_STRING "GB2312"

using namespace SystemTool::Encoding;

// Get gbk wide string
std::wstring Unicode::GetGbkString(const std::string strData, EncodeType eEncodeType)
{
	if (strData.empty())
	{
		return L"";
	}

	std::wstring strFinalData = L"";

	std::string strGbkData = strData;

	std::locale old_loc = std::locale::global(std::locale(""));

	if (eEncodeType == ENCODE_UTF8)
	{
		strGbkData = boost::locale::conv::between(strData, GBK_ENCODE_STRING, UTF8_ENCODE_STRING);
	}

	int iTotalSize = strGbkData.size() + sizeof(int);

	wchar_t* pBuffer = new wchar_t[iTotalSize];

	if (pBuffer == NULL)
	{
		return L"";
	}

	size_t iBufferSize = iTotalSize * sizeof(wchar_t);

	memset(pBuffer, 0, iBufferSize);

	mbstowcs(pBuffer, strGbkData.c_str(), iBufferSize);

	strFinalData = pBuffer;

	if (pBuffer)
	{
		delete[] pBuffer;

		pBuffer = NULL;
	}

	std::locale::global(old_loc);

	return strFinalData;
}

// Get utf8 wide string
std::wstring Unicode::GetUtf8String(const std::string strData, EncodeType eEncodeType)
{
	if (strData.empty())
	{
		return L"";
	}

	if (eEncodeType == ENCODE_UTF8)
	{
		return GetUtf8WString_UTF8(strData);
	}
	else if (eEncodeType == ENCODE_GBK)
	{
		return GetUtf8WString_GBK(strData);
	}
	else if (eEncodeType == ENCODE_GB2312)
	{
		return GetUtf8WString_GB2312(strData);
	}

	return L"";
}

// Get utf8 wide string from utf8 string
std::wstring Unicode::GetUtf8WString_UTF8(const std::string strData)
{
	if (strData.empty())
	{
		return L"";
	}

	try
	{
		return boost::locale::conv::utf_to_utf<wchar_t>(strData);
	}
	catch (std::bad_cast & e)
	{
		throw BSException() << e.what();
	}

	return L"";
}

// Get utf8 wide string from gbk string
std::wstring Unicode::GetUtf8WString_GBK(const std::string strData)
{
	if (strData.empty())
	{
		return L"";
	}

	try
	{
		return boost::locale::conv::to_utf<wchar_t>(strData, GBK_ENCODE_STRING);
	}
	catch (std::bad_cast & e)
	{
		throw BSException() << e.what();
	}

	return L"";
}

// Get utf8 wide string from gb2312 string
std::wstring Unicode::GetUtf8WString_GB2312(const std::string strData)
{
	if (strData.empty())
	{
		return L"";
	}

	try
	{
		return boost::locale::conv::to_utf<wchar_t>(strData, GB2312_ENCODE_STRING);
	}
	catch (std::bad_cast & e)
	{
		throw BSException() << e.what();
	}

	return L"";
}
